﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace DARE
{
    /// <summary>
    /// This class represents a texture for a HUD widget. It's composed of one texture (or animations) for the body of the widget and 8 border textures (4 corners and 4 sides).
    /// If you want an animation on your widget, it's applyable only on the body and you have to see the CAnimationState references.
    /// </summary>
    /// <example>
    /// Here is the XML description of a CHudTexture for a Widget named "MainWindow":
    /// <code>
    /// <Widget name="MainWindow">
    ///    <Textures>
    ///       <Body assetName="DefaultSkin/Skin_Blank"/>
    ///       <Left assetName="DefaultSkin/Skin_L_open" Width="5"/>
    ///       <Right assetName="DefaultSkin/Skin_R_open" Width="5"/>
    ///       <Bottom assetName="DefaultSkin/Skin_EM_open" Height="5"/>
    ///       <BottomLeft assetName="DefaultSkin/Skin_EL_open" Width="5" Height="5"/>
    ///       <BottomRight assetName="DefaultSkin/Skin_ER_open" Width="5" Height="5"/>
    ///    </Textures>
    /// </Widget>
    /// </code>
    /// 
    /// And here, an usage with the CSkinner (the class that loads Cm_hudTextures from xml strings):
    /// <code>
    ///     m_texture = HUD.Skinner.GetTexture("MainWindow");
    /// </code>
    /// </example>
    /// <seealso cref="CAnimationState"/>
    [AttrTypeDependentSerializable(typeof(CHudTextureData))]
    public class CHudTexture
    {
        #region fields

        [ContentSerializerIgnore]
        private SpriteBatch m_spriteBatch;
        private Rectangle m_rect;

        private Texture2D m_body = null;
        [ContentSerializerIgnore]
        private CAnimationState m_anim = null;
        private Nullable<KeyValuePair<Texture2D, Rectangle>> m_top = null;
        private Nullable<KeyValuePair<Texture2D, Rectangle>> m_bottom = null;
        private Nullable<KeyValuePair<Texture2D, Rectangle>> m_left = null;
        private Nullable<KeyValuePair<Texture2D, Rectangle>> m_right = null;

        private Nullable<KeyValuePair<Texture2D, Rectangle>> m_topLeft = null;
        private Nullable<KeyValuePair<Texture2D, Rectangle>> m_topRight = null;
        private Nullable<KeyValuePair<Texture2D, Rectangle>> m_bottomLeft = null;
        private Nullable<KeyValuePair<Texture2D, Rectangle>> m_bottomRight = null;

        #endregion

        #region Properties

        public SpriteBatch SpriteBatch { get { return m_spriteBatch; } set { m_spriteBatch = value; } }

        /// <summary>
        /// Gets/sets the rectangle for the body
        /// </summary>
        public Rectangle Rectangle { get { return m_rect; } set { m_rect = value; } }

        /// <summary>
        /// Gets/sets the body texture
        /// </summary>
        public Texture2D Body { get { return m_body; } set { m_anim.RemoveAll(); m_body = value; m_anim.SpriteSheet = m_body; } }
        
        //public Rectangle BodyAnimationState { set { m_anim.RemoveAll().AddState(value).SetCurrentAnimationState(value); } }
        
        /// <summary>
        /// Gets/sets the animation state for the body of this CHUDTexture
        /// </summary>
        /// <seealso cref="CAnimationState"/>
        public CAnimationState AnimationState { get { return m_anim; } set { m_anim = value; } }



        /// <summary>
        /// Gets/sets the top texture of this CHUDTexture
        /// </summary>
        public Nullable<KeyValuePair<Texture2D, Rectangle>> Top { get { return m_top; } set { m_top = value; } }
        /// <summary>
        /// Gets/sets the bottom texture of this CHUDTexture
        /// </summary>
        public Nullable<KeyValuePair<Texture2D, Rectangle>> Bottom { get { return m_bottom; } set { m_bottom = value; } }
        /// <summary>
        /// Gets/sets the left texture of this CHUDTexture
        /// </summary>
        public Nullable<KeyValuePair<Texture2D, Rectangle>> Left { get { return m_left; } set { m_left = value; } }
        /// <summary>
        /// Gets/sets the right texture of this CHUDTexture
        /// </summary>
        public Nullable<KeyValuePair<Texture2D, Rectangle>> Right { get { return m_right; } set { m_right = value; } }

        /// <summary>
        /// Gets/sets the top-left corner texture of this CHUDTexture
        /// </summary>
        public Nullable<KeyValuePair<Texture2D, Rectangle>> TopLeft { get { return m_topLeft; } set { m_topLeft = value; } }
        /// <summary>
        /// Gets/sets the top-right corner texture of this CHUDTexture
        /// </summary>
        public Nullable<KeyValuePair<Texture2D, Rectangle>> TopRight { get { return m_topRight; } set { m_topRight = value; } }
        /// <summary>
        /// Gets/sets the bottom-left corner texture of this CHUDTexture
        /// </summary>
        public Nullable<KeyValuePair<Texture2D, Rectangle>> BottomLeft { get { return m_bottomLeft; } set { m_bottomLeft = value; } }
        /// <summary>
        /// Gets/sets the bottom-right corner texture of this CHUDTexture
        /// </summary>
        public Nullable<KeyValuePair<Texture2D, Rectangle>> BottomRight { get { return m_bottomRight; } set { m_bottomRight = value; } }

        #endregion

        #region ctor

        public CHudTexture()
        {
            m_anim = new CAnimationState();
        }

        #endregion

        #region methods

        public void RemoveBorders()
        {
            m_left = null;
            m_top = null;
            m_right = null;
            m_bottom = null;
            m_topLeft = null;
            m_topRight = null;
            m_bottomLeft = null;
            m_bottomRight = null;
        }

        public CHudTexture Clone()
        {
            if (m_spriteBatch == null)
                m_spriteBatch = CDare.Instance.SpriteBatch;
            CHudTexture cht = new CHudTexture();
            cht.m_body = m_body;
            cht.m_bottom = m_bottom;
            cht.m_bottomLeft = m_bottomLeft;
            cht.m_bottomRight = m_bottomRight;
            cht.m_left = m_left;
            cht.m_rect = m_rect;
            cht.m_right = m_right;
            cht.m_spriteBatch = m_spriteBatch;
            cht.m_top = m_top;
            cht.m_topLeft = m_topLeft;
            cht.m_topRight = m_topRight;
            cht.m_anim = m_anim.Clone();
            return cht;
        }

        public void Clear()
        {
            m_body = null;
            m_left = null;
            m_top = null;
            m_right = null;
            m_bottom = null;
            m_topLeft = null;
            m_topRight = null;
            m_bottomLeft = null;
            m_bottomRight = null;

        }

        public void Draw(GameTime gameTime)
        {
            if (m_spriteBatch == null)
                m_spriteBatch = CDare.Instance.SpriteBatch;
            Rectangle r;
            if (m_anim != null && m_anim.SpriteSheet != null)
            {
                r = m_rect;
                if (m_top != null)
                {
                    r.Height -= m_top.Value.Value.Height;
                    r.Y += m_top.Value.Value.Height;
                }
                if (m_bottom != null)
                    r.Height -= m_bottom.Value.Value.Height;
                if (m_left != null)
                {
                    r.Width -= m_left.Value.Value.Width;
                    r.X += m_left.Value.Value.Width;
                }
                if (m_right != null)
                    r.Width -= m_right.Value.Value.Width;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_anim.SpriteSheet;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_anim.SpriteSheet, r, m_anim.GetAnimationState(gameTime), Color.White);
                }
            }
            if (m_top != null)
            {
                r = m_top.Value.Value;
                r.Width = m_rect.Width;
                r.X = m_rect.X;
                r.Y = m_rect.Y;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_top.Value.Key;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_top.Value.Key, r, Color.White);
                }
            }
            if (m_bottom != null)
            {
                r = m_bottom.Value.Value;
                r.Width = m_rect.Width;
                r.X = m_rect.X;
                r.Y = m_rect.Y + m_rect.Height - r.Height;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_bottom.Value.Key;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_bottom.Value.Key, r, Color.White);
                }
            }
            if (m_left != null)
            {
                r = m_left.Value.Value;
                r.Height = m_rect.Height;
                r.X = m_rect.X;
                r.Y = m_rect.Y;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_left.Value.Key;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_left.Value.Key, r, Color.White);
                }
            }
            if (m_right != null)
            {
                r = m_right.Value.Value;
                r.Height = m_rect.Height;
                r.X = m_rect.X + m_rect.Width - r.Width;
                r.Y = m_rect.Y;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_right.Value.Key;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_right.Value.Key, r, Color.White);
                }
            }
            if (m_topLeft != null)
            {
                r = m_topLeft.Value.Value;
                r.X = m_rect.X;
                r.Y = m_rect.Y;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_topLeft.Value.Key;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_topLeft.Value.Key, r, Color.White);
                }
            }
            if (m_topRight != null)
            {
                r = m_topRight.Value.Value;
                r.X = m_rect.X + m_rect.Width - r.Width;
                r.Y = m_rect.Y;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_topRight.Value.Key;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_topRight.Value.Key, r, Color.White);
                }
            }
            if (m_bottomLeft != null)
            {
                r = m_bottomLeft.Value.Value;
                r.X = m_rect.X;
                r.Y = m_rect.Y + m_rect.Height - r.Height;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_bottomLeft.Value.Key;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_bottomLeft.Value.Key, r, Color.White);
                }
            }
            if (m_bottomRight != null)
            {
                r = m_bottomRight.Value.Value;
                r.X = m_rect.X + m_rect.Width - r.Width;
                r.Y = m_rect.Y + m_rect.Height - r.Height;
                lock (m_spriteBatch)
                {
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.ColorMap = m_bottomRight.Value.Key;
                    CDare.Instance.SceneMgr.ActiveScene.ActiveHudSystem.Shader.Apply();
                    m_spriteBatch.Draw(m_bottomRight.Value.Key, r, Color.White);
                }
            }
        }

        #endregion
    }
}
